package yueyong.salarymanagement.module.business.salary.controller;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import yueyong.salarymanagement.common.anno.NoValidPrivilege;
import yueyong.salarymanagement.common.domain.ResponseDTO;
import yueyong.salarymanagement.common.idgenerator.IdWorker;
import yueyong.salarymanagement.constant.SwaggerTagConst;
import yueyong.salarymanagement.module.business.salary.domain.entity.EmployeeSalaryEntity;
import yueyong.salarymanagement.module.business.salary.domain.vo.*;
import yueyong.salarymanagement.module.business.salary.service.EmployeeSalaryService;
import yueyong.salarymanagement.module.business.salary.service.SalaryFileService;
import yueyong.salarymanagement.module.system.login.domain.RequestTokenBO;
import yueyong.salarymanagement.util.SmartRequestTokenUtil;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Copyright: yueyong (c) 2022
 *
 * @author he.shaorong
 * @version 1.0
 * @date 2022/2/3
 */
@RestController
@Api(tags = {SwaggerTagConst.Admin.BUSINESS})
public class SalaryFileController {

    private static final Logger logger = LoggerFactory.getLogger(SalaryFileController.class);

    private static final List<String> nameLists = Lists.newArrayList("姓名","中文名","名字","员工姓名", "name");
    private static final List<String> phoneNumberLists = Lists.newArrayList("手机号","电话","移动电话","电话号码", "手机号");
    private static final List<String> emailLists = Lists.newArrayList("邮箱","邮件名","邮箱名称","邮箱地址", "邮件地址", "email", "email-address");
    private static final List<String> paySalaryLists = Lists.newArrayList("实发工资","实发金额","本月实发","薪酬", "到手工资", "income");


    @Autowired
    private SalaryFileService salaryFileService;

    @Autowired
    private EmployeeSalaryService employeeSalaryService;

    //    @ApiOperation(value = "test uploadFile", notes = "test uploadFile")
//    @PostMapping("/uploadFile")
//    @NoValidPrivilege
    public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file) {
        String fileName = salaryFileService.storeFile(file);

        String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/downloadFile/")
                .path(fileName)
                .toUriString();

        return new UploadFileResponse(fileName, fileDownloadUri,
                file.getContentType(), file.getSize());
    }

    //    @ApiOperation(value = "test uploadFile", notes = "test uploadFile")
//    @PostMapping("/user/uploadSalaryFile")
//    @NoValidPrivilege
    public ResponseDTO<UploadFileResponse> uploadSalaryFile(@RequestParam("file") MultipartFile file) {
        String fileName = salaryFileService.storeFile(file);

        String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/downloadFile/")
                .path(fileName)
                .toUriString();

        return ResponseDTO.succData(new UploadFileResponse(fileName, fileDownloadUri,
                file.getContentType(), file.getSize()));
    }


    @ApiOperation(value = "新建工资条 - 上传工资条 - 上传薪资文件，返回解析内容", notes = "上传薪资excel")
    @PostMapping("/user/uploadSalaryFileAndReadExcel")
    @NoValidPrivilege
    public ResponseDTO<SalaryImportDataVO> uploadSalaryFileAndReadExcel(@RequestParam("file") MultipartFile file) {
        String fileName = salaryFileService.storeFile(file);

        SalaryImportDataVO salaryImportDataVO = new SalaryImportDataVO();
        salaryImportDataVO.setSuccess(true);

        IdWorker idWorker = new IdWorker(0, 0);
        long salaryId = idWorker.nextId();
        salaryImportDataVO.setSalaryId(salaryId);

        Pair<List<List<ItemData>>, Map<Integer, String>> excelDataPair = salaryFileService.readExcel(fileName);

        List<EmployeeSalaryDataVO> employeeSalaryDataVOList = excelDataPair.getLeft().stream()
                .map(itemDataList -> new EmployeeSalaryDataVO(itemDataList, idWorker.nextId()))
                .filter(i -> i.getSalaryData().size() >4 ).collect(Collectors.toList());
//        salaryImportDataVO.setExcelDetailInfos(employeeSalaryDataVOList);
//        salaryImportDataVO.setTitleMap(excelDataPair.getRight());

        //设置表头
        List<ItemData> titleList = Lists.newArrayList();
        for (Map.Entry<Integer, String> map : excelDataPair.getRight().entrySet()) {
            titleList.add(new ItemData(map.getKey(), map.getValue(), ""));
        }
        titleList.sort(Comparator.comparing(ItemData::getItemId));
        salaryImportDataVO.setTitleList(titleList);

        //设置填平缺失值的Detail
        salaryImportDataVO.setExcelDetailInfosNew(resolveNullData(employeeSalaryDataVOList,titleList));

        salaryImportDataVO.setExcelTitleMaps(new TitleMapsData());

        boolean result = insertRecords(employeeSalaryDataVOList, excelDataPair.getRight(), idWorker, salaryId);

        return ResponseDTO.succData(salaryImportDataVO);
    }

    private List<EmployeeSalaryDataVO> resolveNullData(List<EmployeeSalaryDataVO> employeeSalaryDataVOList, List<ItemData> titleList) {
        List<EmployeeSalaryDataVO> resolvedDataList = Lists.newArrayList();

        for (EmployeeSalaryDataVO dataVOBefore : employeeSalaryDataVOList) {
            EmployeeSalaryDataVO dataVO = new EmployeeSalaryDataVO();
            dataVO.setEmployeeId(dataVOBefore.getEmployeeId());
            List<ItemData> solvedItemData = Lists.newArrayList();
            for (ItemData itemData : titleList) {
                ItemData newItemData = new ItemData();
                newItemData.setItemId(itemData.getItemId());
                newItemData.setItemName(itemData.getItemName());
                ItemData itemDataBefore = dataVOBefore.getSalaryData().stream()
                        .filter(item -> item.getItemId() == itemData.getItemId() && item.getItemName().equalsIgnoreCase(itemData.getItemName())).findFirst().orElse(null);

                newItemData.setItemValue(itemDataBefore == null ? "" : itemDataBefore.getItemValue());
                solvedItemData.add(newItemData);
            }
            dataVO.setSalaryData(solvedItemData);
            resolvedDataList.add(dataVO);

        }


        return resolvedDataList;
    }


    //    @ApiOperation(value = "test uploadMultipleFiles", notes = "test uploadMultipleFiles")
//    @PostMapping("/uploadMultipleFiles")
    public List<UploadFileResponse> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
        return Arrays.stream(files)
                .map(this::uploadFile)
                .collect(Collectors.toList());
    }

    //    @ApiOperation(value = "test downloadFile", notes = "test downloadFile")
//    @GetMapping("/downloadFile/{fileName:.+}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request) {
        // Load file as Resource
        Resource resource = salaryFileService.loadFileAsResource(fileName);

        // Try to determine file's content type
        String contentType = null;
        try {
            contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
        } catch (IOException ex) {
            logger.info("Could not determine file type.");
        }

        // Fallback to the default content type if type could not be determined
        if (contentType == null) {
            contentType = "application/octet-stream";
        }

        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(contentType))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                .body(resource);
    }

    private boolean insertRecords(List<EmployeeSalaryDataVO> data, Map<Integer, String> headData, IdWorker idWorker, long salaryId) {
        for (EmployeeSalaryDataVO item : data) {
            SalaryImportData salaryImportData = new SalaryImportData();
            salaryImportData.setSalaryData(item.getSalaryData());
            salaryImportData.setTitleMap(headData);

            //转成JSON对象
            JSONObject jsonObject = (JSONObject) JSONObject.toJSON(salaryImportData);
            String jsonStr = jsonObject.toJSONString();

            RequestTokenBO requestToken = SmartRequestTokenUtil.getRequestUser();
            Long uid = requestToken.getRequestUserId();

            EmployeeSalaryEntity entity = buildEmployeeSalaryEntity(jsonStr, item, salaryId, uid);
            int result = employeeSalaryService.addEmployeeSalaryEntity(entity);
        }

        return true;
    }

    private EmployeeSalaryEntity buildEmployeeSalaryEntity(String jsonStr, EmployeeSalaryDataVO item, long salaryId
            , long uid) {
        EmployeeSalaryEntity entity = new EmployeeSalaryEntity();
        entity.setUid(uid);
        entity.setSalaryId(salaryId);
        entity.setSalaryItems(jsonStr);
        entity.setEmployeeId(item.getEmployeeId());
        entity.setPayDate(Timestamp.from(Instant.now()));

        ItemData payItem = getAssignedItemValue(item.getSalaryData(), paySalaryLists);
        entity.setPayAmount(payItem == null ? BigDecimal.ZERO : new BigDecimal(payItem.getItemValue().replace(",", "")));
        entity.setPayItemId(payItem.getItemId());
        entity.setState(-1);
        entity.setMsgSendTime(Timestamp.from(Instant.now()));
        entity.setStateReason("init");
        entity.setSendType(-1);
        ItemData mobilePhoneItem = getAssignedItemValue(item.getSalaryData(), phoneNumberLists);
        entity.setMobilePhone(mobilePhoneItem == null ? 0 : Long.valueOf(mobilePhoneItem.getItemValue()));

        ItemData emailItem = getAssignedItemValue(item.getSalaryData(), emailLists);
        entity.setEmailAddress(emailItem == null ? "-" : emailItem.getItemValue());

        ItemData nameItem = getAssignedItemValue(item.getSalaryData(), nameLists);
        entity.setEmployeeName(nameItem == null ? "-" : nameItem.getItemValue());
        return entity;
    }


    private ItemData getAssignedItemValue(List<ItemData> itemDataList, List<String> name) {
        ItemData data = itemDataList.stream().filter(itemData -> name.contains(itemData.getItemName().trim().toLowerCase())).findFirst().orElse(null);
        if (data != null) {
            return data;
        }
        return null;
    }

}
